package com.red.wood.common.util;
import java.io.IOException;
import java.io.OutputStream;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFColor;
import org.apache.poi.xssf.usermodel.XSSFFont;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
 
/**
 * 导出Excel
 */
public class ExportExcelUtil{
	
	private static final Log log = LogFactory.getLog(ExportExcelUtil.class);
	
	// 2007 版本以上 最大支持1048576行
	public  final static String  EXCEl_FILE_2007 = "2007";
	// 2003 版本 最大支持65536 行
	public  final static String  EXCEL_FILE_2003 = "2003";
	
	/**
	 * @param title 表格标题
	 * @param headers 头部标题集合
	 * @param mapKey map集合中key
	 * @param dataset 数据集合
	 * @param out 输出流
	 * @param version 2003 或者 2007，不传时默认生成2003版本
	 */
	public void exportExcel(String title,String[] headers,String[] columnsWidth,String[] mapKey,List<Map<String,Object>> dataset, OutputStream out,String version) {
		if(StringUtils.isBlank(version) || EXCEL_FILE_2003.equals(version.trim())){
			exportExcel2003(title,headers,columnsWidth,mapKey,dataset,out);
		}else{
			exportExcel2007(title,headers,columnsWidth,mapKey,dataset,out);
		}
	}
 
	/**
	 * 此版本生成2007以上版本的文件 (文件后缀：xlsx)
	 * @param title 表格标题名
	 * @param headers 表格头部标题集合
	 * @param dataset
	 * @param out 与输出设备关联的流对象，可以将EXCEL文档导出到本地文件或者网络中
	 */
	public void exportExcel2007(String title, String[] headers,String[] columnsWidth,String[] mapKey, List<Map<String,Object>> dataset, OutputStream out) {
		// 声明一个工作薄
		XSSFWorkbook workbook = new XSSFWorkbook();
		// 生成一个表格
		XSSFSheet sheet = workbook.createSheet(title);
		// 设置表格默认列宽度为18个字节
		sheet.setDefaultColumnWidth(18);
		setColumnsWidth(sheet,columnsWidth);
		//sheet.setColumnWidth(0,256*40);//setDefaultColumnWidth设置的单位不一样
		// 生成一个样式
		XSSFCellStyle style = workbook.createCellStyle();
		// 设置这些样式
		style.setFillForegroundColor(new XSSFColor(java.awt.Color.gray));
		style.setFillPattern(XSSFCellStyle.SOLID_FOREGROUND);
		style.setBorderBottom(XSSFCellStyle.BORDER_THIN);
		style.setBorderLeft(XSSFCellStyle.BORDER_THIN);
		style.setBorderRight(XSSFCellStyle.BORDER_THIN);
		style.setBorderTop(XSSFCellStyle.BORDER_THIN);
		style.setAlignment(XSSFCellStyle.ALIGN_CENTER);
		// 生成一个字体
		XSSFFont font = workbook.createFont();
		font.setBoldweight(XSSFFont.BOLDWEIGHT_BOLD);
		font.setFontName("宋体"); 
		font.setColor(new XSSFColor(java.awt.Color.BLACK));
		font.setFontHeightInPoints((short) 11);
		// 把字体应用到当前的样式
		style.setFont(font);
		// 生成并设置另一个样式
		XSSFCellStyle style2 = workbook.createCellStyle();
		style2.setFillForegroundColor(new XSSFColor(java.awt.Color.WHITE));
		style2.setFillPattern(XSSFCellStyle.SOLID_FOREGROUND);
		style2.setBorderBottom(XSSFCellStyle.BORDER_THIN);
		style2.setBorderLeft(XSSFCellStyle.BORDER_THIN);
		style2.setBorderRight(XSSFCellStyle.BORDER_THIN);
		style2.setBorderTop(XSSFCellStyle.BORDER_THIN);
		style2.setAlignment(XSSFCellStyle.ALIGN_CENTER);
		style2.setVerticalAlignment(XSSFCellStyle.VERTICAL_CENTER);
		// 生成另一个字体
		XSSFFont font2 = workbook.createFont();
		font2.setBoldweight(XSSFFont.BOLDWEIGHT_NORMAL);
		// 把字体应用到当前的样式
		style2.setFont(font2);
 
		// 产生表格标题行
		XSSFRow row = sheet.createRow(0);
		XSSFCell cellHeader;
		for (int i = 0; i < headers.length; i++) {
			cellHeader = row.createCell(i);
			cellHeader.setCellStyle(style);
			cellHeader.setCellValue(new XSSFRichTextString(headers[i]));
		}
		int index = 0;
		XSSFCell cell;
		// 遍历集合数据，产生数据行
		for(Map<String,Object> map : dataset) {
			index++;
			row = sheet.createRow(index);
			for(int i = 0 ; i < mapKey.length ; i++) {
				Object value = map.get(mapKey[i]);
				cell = row.createCell(i);
				cell.setCellStyle(style2);
				if(value == null) {
					cell.setCellValue("");
				}else {
					//因为有关数值长度大于15位会导致数据丢失，所以所有数值都按文本处理
	                cell.setCellValue(new XSSFRichTextString(value.toString()));
				}
			}
		}
		try {
			workbook.write(out);
		} catch (IOException e) {
			if(log.isErrorEnabled()) {
				log.error(e.getMessage(),e);
			}
		}finally {
			try {
				workbook.close();
			} catch (IOException e) {
				if(log.isErrorEnabled()) {
					log.error(e.getMessage(),e);
				}
			}
		}
	}
	
	/**
	 * 此方法生成2003版本的excel,文件名后缀：xls <br>
	 * @param title 表格标题名
	 * @param headers 表格头部标题集合
	 * @param mapKey map中的key
	 * @param dataset 数据集
	 * @param out 与输出设备关联的流对象，可以将EXCEL文档导出到本地文件或者网络中
	 */
	public void exportExcel2003(String title, String[] headers,String[] columnsWidth,String[] mapKey,List<Map<String,Object>> dataset, OutputStream out) {
		// 声明一个工作薄
		HSSFWorkbook workbook = new HSSFWorkbook();
		// 生成一个表格
		HSSFSheet sheet = workbook.createSheet(title);
		// 设置表格默认列宽度为18个字节
		sheet.setDefaultColumnWidth(30);
		setColumnsWidth(sheet,columnsWidth);
		// 生成一个样式
		HSSFCellStyle style = workbook.createCellStyle();
		// 设置这些样式
		style.setFillForegroundColor(HSSFColor.GREY_50_PERCENT.index);
		style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
		style.setBorderBottom(HSSFCellStyle.BORDER_THIN);
		style.setBorderLeft(HSSFCellStyle.BORDER_THIN);
		style.setBorderRight(HSSFCellStyle.BORDER_THIN);
		style.setBorderTop(HSSFCellStyle.BORDER_THIN);
		style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
		// 生成一个字体
		HSSFFont font = workbook.createFont();
		font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
		font.setFontName("宋体"); 
		font.setColor(HSSFColor.WHITE.index);
		font.setFontHeightInPoints((short) 11);
		// 把字体应用到当前的样式
		style.setFont(font);
		// 生成并设置另一个样式
		HSSFCellStyle style2 = workbook.createCellStyle();
		style2.setFillForegroundColor(HSSFColor.WHITE.index);
		style2.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
		style2.setBorderBottom(HSSFCellStyle.BORDER_THIN);
		style2.setBorderLeft(HSSFCellStyle.BORDER_THIN);
		style2.setBorderRight(HSSFCellStyle.BORDER_THIN);
		style2.setBorderTop(HSSFCellStyle.BORDER_THIN);
		style2.setAlignment(HSSFCellStyle.ALIGN_CENTER);
		style2.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
		// 生成另一个字体
		HSSFFont font2 = workbook.createFont();
		font2.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL);
		// 把字体应用到当前的样式
		style2.setFont(font2);
 
		// 产生表格标题行
		HSSFRow row = sheet.createRow(0);
		HSSFCell cellHeader;
		for (int i = 0; i < headers.length; i++) {
			cellHeader = row.createCell(i);
			cellHeader.setCellStyle(style);
			cellHeader.setCellValue(new HSSFRichTextString(headers[i]));
		}
		HSSFCell cell;
		int index = 0;
		for(Map<String,Object> map : dataset) {
			index++;
			row = sheet.createRow(index);
			for(int i = 0 ; i < mapKey.length ; i++) {
				Object value = map.get(mapKey[i]);
				cell = row.createCell(i);
				cell.setCellStyle(style2);
				if(value == null) {
					cell.setCellValue("");
				}else {
					//因为有关数值长度大于15位会导致数据丢失，所以所有数值都按文本处理
	                cell.setCellValue(new HSSFRichTextString(value.toString()));
				}
			}
		}
		try {
			workbook.write(out);
		} catch (IOException e) {
			if(log.isErrorEnabled()) {
				log.error(e.getMessage(),e);
			}
		}finally {
			try {
				workbook.close();
			} catch (IOException e) {
				if(log.isErrorEnabled()) {
					log.error(e.getMessage(),e);
				}
			}
		}
	}
	
	public void setColumnsWidth(Sheet sheet,String[] columnsWidth) {
		try {
			if(columnsWidth != null) {
				for(String column : columnsWidth) {
					String[] split = column.split(":");
					sheet.setColumnWidth(Integer.parseInt(split[0]),Integer.parseInt(split[1])*256);//setDefaultColumnWidth设置的单位不一样
				}
			}
		}catch(Exception e) {
			if(log.isErrorEnabled()) {
				log.error(e.getMessage(),e);
			}
		}
	}
}